<template>
  <div class="container">
    <div
      class="loading"
      v-loading="showLoading"
      element-loading-text="正在拼命初始化..."
      element-loading-background="rgba(0, 0, 0, 0.8)"
    >
      <div class="chat-wrapper">
        <current-conversation />
      </div>
      <call-layer
        ref="callLayer"
        class="chat-wrapper"
      />
      <image-previewer />
    </div>
    <div class="bg" />
  </div>
</template>

<script>
    import TIM from 'tim-js-sdk'
    import { mapState } from 'vuex'
    import { showError, showSuccess } from '@/util/message';
    import { infoNotification } from '@/util/notification'
    import { ACTION } from '@/util/trtc-custom-message-map'

    import CurrentConversation from '@/components/conversation/current-conversation'
    import CallLayer from '@/components/message/call-layer'
    import ImagePreviewer from '@/components/message/image-previewer'

    export default {
        name: "Tim",
        components: {
            CurrentConversation,
            ImagePreviewer,
            CallLayer
        },
        data() {
            return {

            }
        },
        computed: {
            ...mapState(['isSdkReady', 'isBusy', 'userID', 'userSig']),
            // 是否显示 Loading 状态
            showLoading() {
                return !this.isSdkReady
            }
        },
        created() {
            // 初始化监听器
            this.initListener()
            // 登录
            this.login()
        },
        beforeDestroy() {
            // 停止定时器
            this.$store.dispatch('logout')
        },
        methods: {
            login() {
                this.$tim.login({
                    userID: this.userID,
                    userSig: this.userSig
                }).then(() => {
                    // 开始记录当前时间
                    this.$store.commit('startComputeCurrent')
                    showSuccess('登录成功')
                }).catch(error => {
                    showError(`登录失败：${error.message}`)
                })
            },
            initListener() {
                // 登录成功后会触发 SDK_READY 事件，该事件触发后，可正常使用 SDK 接口
                this.$tim.on(TIM.EVENT.SDK_READY, this.onReadyStateUpdate, this)
                // SDK NOT READY
                this.$tim.on(TIM.EVENT.SDK_NOT_READY, this.onReadyStateUpdate, this)
                // 被踢出
                this.$tim.on(TIM.EVENT.KICKED_OUT, this.onKickOut)
                // SDK内部出错
                this.$tim.on(TIM.EVENT.ERROR, this.onError)
                // 收到新消息
                this.$tim.on(TIM.EVENT.MESSAGE_RECEIVED, this.onReceiveMessage)
                // 会话列表更新
                this.$tim.on(TIM.EVENT.CONVERSATION_LIST_UPDATED, this.onUpdateConversationList)
            },
            // 处理接收到消息
            onReceiveMessage({ data: messageList }) {
                this.handleVideoMessage(messageList)
                this.handleAt(messageList)
                this.$store.commit('pushCurrentMessageList', messageList)
            },
            onError({ data }) {
              console.log(data)
                if (data.message !== 'Network Error') {
                    showError(data.message)
                }
            },
            // SDK 准备好了，也就是用户登录成功了
            onReadyStateUpdate({ name }) {
                const isSdkReady = name === TIM.EVENT.SDK_READY
                this.$store.commit('setSdkReady', isSdkReady)

                if (isSdkReady) {
                    this.$tim.getMyProfile()
                        .then(({ data }) => {
                            this.$store.commit('updateCurrentUserProfile', data)
                        })
                        .catch(error => {
                            showError(error.message)
                        })
                    // checkout 会话
                    this.$store.dispatch('checkoutConversation', 'C2Ctest2')
                }
            },
            kickedOutReason(type) {
                switch (type) {
                    case this.$types.KICKED_OUT_MULT_ACCOUNT:
                        return '由于多实例登录'
                    case this.$types.KICKED_OUT_MULT_DEVICE:
                        return '由于多设备登录'
                    case this.$types.KICKED_OUT_USERSIG_EXPIRED:
                        return '由于 userSig 过期'
                    default:
                        return ''
                }
            },
            onKickOut(event) {
                showError(`${this.kickedOutReason(event.data.type)}被踢出，请重新登录。`)
                this.$store.commit('reset')
            },
            onUpdateConversationList(event) {
                this.$store.commit('updateConversationList', event.data)
            },
            /**
             * 处理 @ 我的消息
             * @param {Message[]} messageList
             */
            handleAt(messageList) {
                // 筛选有 @ 符号的文本消息
                const atTextMessageList = messageList.filter(
                    message => message.type === this.$types.MSG_TEXT && message.payload.text.includes('@')
                )
                for (let i = 0; i < atTextMessageList.length; i++) {
                    const message = atTextMessageList[i]
                    const matched = message.payload.text.match(/@\w+/g)
                    if (!matched) {
                        continue
                    }
                    // @ 我的
                    if (matched.includes(`@${this.currentUserProfile.userID}`)) {
                        // 当前页面不可见时，调用window.Notification接口，系统级别通知。
                        if (this.$store.getters.hidden) {
                            this.notifyMe(message)
                        }
                        infoNotification('有人提到了你', message.payload.text)
                        this.$bus.$emit('new-message-at-me', {
                            data: { conversationID: message.conversationID }
                        })
                    }
                }
            },
            selectConversation(conversationID) {
                if (conversationID !== this.currentConversation.conversationID) {
                    this.$store.dispatch('checkoutConversation',conversationID)
                }
            },
            isJsonStr(str) {
                try{
                    JSON.parse(str)
                    return true
                }catch {
                    return false
                }
            },
            handleVideoMessage(messageList) {
                const videoMessageList = messageList.filter(
                    message => message.type === this.$types.MSG_CUSTOM && this.isJsonStr(message.payload.data)
                )
                if (videoMessageList.length === 0) {
                    return
                }
                const videoPayload = JSON.parse(videoMessageList[0].payload.data)
                if (videoPayload.action === ACTION.VIDEO_CALL_ACTION_DIALING) {
                    if (this.isBusy) {
                        this.$bus.$emit('busy', videoPayload, videoMessageList[0])
                        return
                    }
                    this.$store.commit('genVideoRoomId', videoPayload.room_id)
                    this.selectConversation(videoMessageList[0].conversationID) // 切换当前会话页
                    if (videoMessageList[0].from !== this.userID) {
                        this.$bus.$emit('isCalled')
                    }
                }
                if (videoPayload.action === ACTION.VIDEO_CALL_ACTION_SPONSOR_CANCEL) {
                    this.$bus.$emit('missCall')
                }
                if (videoPayload.action === ACTION.VIDEO_CALL_ACTION_REJECT) {
                    this.$bus.$emit('isRefused')
                }
                if (videoPayload.action === ACTION.VIDEO_CALL_ACTION_SPONSOR_TIMEOUT) {
                    this.$bus.$emit('missCall')
                }
                if (videoPayload.action === ACTION.VIDEO_CALL_ACTION_ACCEPTED) {
                    this.$bus.$emit('isAccept')
                }
                if (videoPayload.action === ACTION.VIDEO_CALL_ACTION_HANGUP) {
                    this.$bus.$emit('isHungUp')
                }
                if (videoPayload.action === ACTION.VIDEO_CALL_ACTION_LINE_BUSY) {
                    this.$bus.$emit('isRefused')
                }
                if (videoPayload.action === ACTION.VIDEO_CALL_ACTION_ERROR) {
                    this.$bus.$emit('isRefused')
                }
            },
            /**
             * 使用 window.Notification 进行全局的系统通知
             * @param {Message} message
             */
            notifyMe(message) {
                // 需检测浏览器支持和用户授权
                if (!('Notification' in window)) {
                    return
                }
                if (window.Notification.permission === 'granted') {
                    this.handleNotify(message)
                } else if (window.Notification.permission !== 'denied') {
                    window.Notification.requestPermission().then(permission => {
                        // 如果用户同意，就可以向他们发送通知
                        if (permission === 'granted') {
                            this.handleNotify(message)
                        }
                    })
                }
            },
            handleNotify(message) {
                const notification = new window.Notification('有人提到了你', {
                    icon: 'https://webim-1252463788.file.myqcloud.com/demo/img/logo.dc3be0d4.png',
                    body: message.payload.text
                })
                notification.onclick = () => {
                    window.focus()
                    this.$store.dispatch('checkoutConversation', message.conversationID)
                    notification.close()
                }
            },
        }
    }
</script>

<style lang="stylus" scoped>
    body {
        margin: 0;
        font-family: 'Microsoft YaHei', 'PingFang SC', '微软雅黑', 'MicrosoftJhengHei', 'Lantinghei SC', 'Open Sans', 'Arial', 'Hiragino Sans GB', 'STHeiti', 'WenQuanYi Micro Hei', 'SimSun', 'sans-serif';
        background-color: $bg;
        -ms-scroll-chaining: chained;
        -ms-content-zooming: zoom;
        -ms-scroll-rails: none;
        -ms-content-zoom-limit-min: 100%;
        -ms-content-zoom-limit-max: 500%;
        -ms-scroll-snap-type: proximity;
        -ms-scroll-snap-points-x: snapList(100%, 200%, 300%, 400%, 500%);
        -ms-overflow-style: none;
        overflow: auto;

        div {
            box-sizing: border-box;

            &::before, &::after {
                box-sizing: border-box;
            }
        }
    }

    #wrapper {
        display: flex;
        justify-content: center;
        align-items: center;
        flex-direction: column;
        padding-top: 100px;
    }

    .container
        position relative
        height 100vh
    .container
        position relative
        height 100vh
    // TODO filter mac chrome 会有问题，下次修改可以去掉
    .bg {
        position: absolute;
        width: 100%;
        height: 100%;
        top: 0;
        left: 0;
        z-index: -1;
        background: url('~@/assets/images/bg.jpg') no-repeat 0 0;
        background-size: cover;
        // filter blur(67px)
    }

    .loading {
        height: 100vh;
        width: 100vw;
        display: flex;
        justify-content: center;
    }

    .text-ellipsis {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .chat-wrapper {
        margin-top: 8vh;
        width: $width;
        height: $height;
        max-width: 1280px;
        box-shadow: 0 11px 20px 0 rgba(0, 0, 0, 0.3);
    }

    /* 设置滚动条的样式 */
    ::-webkit-scrollbar {
        width: 3px;
        height: 3px;
    }

    /* 滚动槽 */
    ::-webkit-scrollbar-track {
        border-radius: 10px;
    }

    /* 滚动条滑块 */
    ::-webkit-scrollbar-thumb {
        border-radius: 10px;
        background: rgba(0, 0, 0, 0.1);
    }
</style>